package _11_整理题目._1_链表指针._环节点;

import org.junit.Test;
import util.ListNode;

import java.util.HashSet;
import java.util.Set;

/**
 * 判断一个链表中是否有环
 * 
 * 1 使用快慢指针判断
 *      初始化快慢指针为 head
 *      遍历整个 链表，如果 快指针 fast.next!=null && fast.next.next!=null
 *          快指针每次走两步，慢指针针每次走一步
 *          如果相遇相等则有环
 *      遍历完说明没环
 *      
 * 2 使用集合 set 判断
 *      从头遍历链表，while(head!=null)
 *          如果 set 里 contains(head)
 *              说明有环
 *          否则添加进去，遍历
 *      遍历完说明没环
 */
public class _02_判断链表中是否有环 {
    
    public boolean hasCycle1(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {// 因为快指针走得快，循环条件判断快指针
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                return true;
            }
        }
        return false;
    }
    
    public boolean hasCycle2(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        while(head != null) {
            if(set.contains(head)){
                return true;
            } else {
                set.add(head);
                head = head.next;
            }
        }
        return false;
    }
    
    @Test
    public void main() {
        Integer[] array = {1, 2, 3, 4};
        ListNode head = ListNode.getListFromArray(array);
        System.out.println(head.val);
        System.out.println(hasCycle1(head));
        System.out.println(hasCycle2(head));
        
        head.next.next = head.next;
        System.out.println(hasCycle1(head));
        System.out.println(hasCycle2(head));
    }
    
}
